#include <Resource2.h>
#include <iostream>
#include <Threading.h>
using namespace std;

int main()
{ 
	cout<<"Resource\n";
	
	Client client_obj; 		// Create Client object.

	client_obj.CreateSocket(TCPSOCKET);	// Create Client Socket.
	client_obj.SetSocketOptions();

	client_obj.InitialiseAddress(DEFAULTCLIENTPORT);	// Without any argument default port will be chosen.
	client_obj.Bind();

	char server_name[24]="localhost";
	int server_port=5000;
	cout << "Enter Server name or IP: "; // Use localhost or 127.0.0.1 for local server.
	cin.getline(server_name, 24);
	//cout << "Server name or IP: "; // Use localhost or 127.0.0.1 for local server.
	//cout<< server_name<<endl;
	//cout << "Enter Server port: ";
	cout << "\nServer port: ";
	cout << server_port<<endl;
	//cin >> server_port;
	cout<<"Connected to server.."<<endl;
	// Connect to Server. Server name/IP and port are provided as arguments.
	client_obj.Connect(server_name, server_port);

	WindowsThreading Obj;
	while(true)
	{
		

		/** recieving **/
		int *recived_buffer,*recived_bufferi,*recived_bufferj,*recived_size;
		int start_matrix_A, end_matrix_A;	
		client_obj.Receive();
		char* buff1	 =	client_obj.GetBuffer();
		recived_size =  (int*)buff1;
		char reply[]	= "Size received\n";
		int total_bytes	= recived_size[0];
		cout<<"size recieved by resource  "<<endl;
		client_obj.Send((void*)reply,sizeof(reply));
		recived_bufferj	= new int[total_bytes/4];
		recived_bufferi	= new int[total_bytes/4];
		int recived_bytes = 0;
		while(true)
		{
			if(client_obj.GetNumOfBytesReceived()==-1 || recived_bytes>=total_bytes)
				break;
			client_obj.Receive((void*)(recived_bufferi),(int)total_bytes);
	//		cout<<client_data->server_obj->GetNumOfBytesReceived(client_data->thread_number)<<endl;
			Obj.MemoryCopy((char*)(recived_bufferj)+recived_bytes,(char*)recived_bufferi,client_obj.GetNumOfBytesReceived());
			recived_bytes += client_obj.GetNumOfBytesReceived();
		}
		cout << "No. of Bytes received: " <<recived_bytes<< endl;
		unsigned char keydata[] = "nucesfast";
		char *Decrypted = Encrypt(keydata, (char*)recived_bufferj, total_bytes);
		recived_buffer = (int*)Decrypted;
	
		/** setting the values **/
		Obj.SetNumberOfThreads(8);
		Obj.SetRowsMatrixA(recived_buffer[0]);
		Obj.SetColumsMatrixA(recived_buffer[1]);
		Obj.SetRowsMatrixB(recived_buffer[2]);
		Obj.SetColumsMatrixB(recived_buffer[3]);
		start_matrix_A = recived_buffer[4];
		end_matrix_A = recived_buffer[5];
		Obj.SetMatrixA( recived_buffer+HEADERSIZE + start_matrix_A*Obj.GetColumsMatrixA());
		Obj.SetMatrixB(recived_buffer + (Obj.GetRowsMatrixA())*(Obj.GetColumsMatrixA()) + HEADERSIZE);
		Obj.SetRowsMatrixA(end_matrix_A - start_matrix_A);
		/** creating data structure for threading **/
		DataForThreadFunc *data_for_thread_func = new DataForThreadFunc[Obj.GetNumberOfThreads()]; //object=number of threads
		for(int i=0; i<Obj.GetNumberOfThreads(); i++)
		{
			data_for_thread_func[i].current_object = &Obj;	//assigning same object address to all data structure
			data_for_thread_func[i].thread_number = 0;		//intializing
		}
	
		/** Dynamically Assigning memory **/
		Obj.AssignMemory(MATRIXC);
		Obj.AssignMemory(MATRIXBTRANSPOSE);


		/** creating dynamic thread array **/
		HANDLE* thread_array;
		thread_array = new HANDLE[Obj.GetNumberOfThreads()];

	
		Obj.MatrixTranspose(); //B transpose
		for(int thread_counter=0; thread_counter<Obj.GetNumberOfThreads(); thread_counter++)
		{	
			data_for_thread_func[thread_counter].thread_number = thread_counter;
			thread_array[thread_counter] = (HANDLE)_beginthread(ThreadFunction,0,(void*)&data_for_thread_func[thread_counter]);
		}
		for (int thread_counter=0; thread_counter<Obj.GetNumberOfThreads(); thread_counter++)
		WaitForSingleObject(thread_array[thread_counter], INFINITE);
	

		/** Sending**/
		cout<<"Start Sending result"<<endl;
		int	matrixC_length=Obj.GetColumsMatrixB()* Obj.GetRowsMatrixA();
		unsigned char *matrix_C_Buffer= new unsigned char[sizeof(int)*matrixC_length];
		memcpy(matrix_C_Buffer, Obj.GetMatrixC(), sizeof(int)*matrixC_length);
		int totalbytes1=matrixC_length*4;
		int sentbytes=0;
		char *Encrypted = Encrypt(keydata, (char*)matrix_C_Buffer, totalbytes1);
		delete matrix_C_Buffer;
		while(true)
		{
			if(client_obj.GetNumOfBytesSent()==-1 || sentbytes>=totalbytes1)
				break;
			client_obj.Send((void*)(Encrypted+sentbytes),totalbytes1);//sending matrix 
			sentbytes+=client_obj.GetNumOfBytesSent();
		}
		Obj.MatrixStore(MATRIXC);

		cout<<"Sending done"<<endl;
		delete Encrypted;
		delete recived_bufferi;
		delete recived_bufferj;
		delete recived_buffer;
		Obj.DeleteMemory(MATRIXC);
		Obj.DeleteMemory(MATRIXBTRANSPOSE);

		/** Storing in files **/
	//	Obj.MatrixStore(MATRIXA);
	//	Obj.MatrixStore(MATRIXB);
	}
	return 0;
}
